package com.sunwayhorizo.health.business.base.query;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.jboss.seam.annotations.Logger;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.log.Log;

import com.sunwayhorizo.health.common.ListUtil;
import com.sunwayhorizo.health.common.StrUtil;
import com.sunwayhorizo.health.hl7.common.Hl7Exception;
import com.sunwayhorizo.health.hl7.rim.Act;
import com.sunwayhorizo.health.hl7.rim.ActParticipation;
import com.sunwayhorizo.health.hl7.rim.Document;
import com.sunwayhorizo.health.hl7.rim.Hl7Entity;
import com.sunwayhorizo.health.hl7.rim.Role;
import com.sunwayhorizo.health.hl7.vocabulary.RoleIICode;

@Name("BaseQuery")
@Stateless
public class BaseQuery implements BaseQueryLocal
{

    @PersistenceContext(unitName = "sunwayhealth")
    public EntityManager em;

    @Logger
    public Log log;

    public Map<String, Map<String, Object>> conditions = new HashMap<String, Map<String, Object>>();


    @SuppressWarnings("unchecked")
    public boolean findRimCoreEntyIiByCode(String code) throws Hl7Exception
    {
        String jpql = " select eii.entityIiId from RimCoreEntyIi eii where eii.extensionTxt='" + code + "'";
        List<String> list = em.createQuery(jpql).getResultList();
        if (ListUtil.isNotEmpty(list))
        {
            return false;
        }
        return true;
    }


    @SuppressWarnings("unchecked")
    public Hl7Entity findHl7EntityById(Long entityId) throws Hl7Exception
    {
        if (entityId == null)
            return null;
        StringBuilder jpql = new StringBuilder();
        jpql.append(" select e from Hl7Entity e ");
        jpql.append(" where e.entityId=" + entityId);
        List<Hl7Entity> ll7EntityList = em.createQuery(jpql.toString()).getResultList();
        if (ListUtil.isNotEmpty(ll7EntityList))
        {
            return (Hl7Entity) ll7EntityList.get(0);
        }
        return null;
    }


    @SuppressWarnings("unchecked")
    public boolean findRimCoreRoleIiByCode(String code)
    {
        String jpql = " select rii.roleIiId from RimCoreRoleIi rii where rii.extensionTxt='" + code + "'";
        List<String> list = em.createQuery(jpql).getResultList();
        if (ListUtil.isNotEmpty(list))
        {
            return false;
        }
        return true;
    }


    @Override
    public Role findRoleByII(String ii, String identifierName)
    {
        StringBuilder jpql = new StringBuilder();
        jpql.append("select r from Role r left join r.roleIiList rii where rii.extensionTxt=");
        jpql.append(convertInJpql(ii));
        jpql.append(" and rii.identifierName=");
        jpql.append(convertInJpql(identifierName));
        @SuppressWarnings("unchecked")
        List<Role> roles = em.createQuery(jpql.toString()).getResultList();

        if (roles.isEmpty())
        {
            return null;
        }
        else
        {
            return roles.get(0);
        }
    }


    @SuppressWarnings("unchecked")
    public Role findRoleById(Long roleId) throws Hl7Exception
    {
        if (roleId == null)
        {
            return null;
        }
        StringBuilder jpql = new StringBuilder();
        jpql.append(" select r from Role r ");
        jpql.append(" where r.roleId=" + roleId);
        List<Role> roleList = em.createQuery(jpql.toString()).getResultList();
        if (ListUtil.isNotEmpty(roleList))
        {
            return (Role) roleList.get(0);
        }
        return null;
    }





    @Override
    public Act findActByActId(Long actId) throws Hl7Exception
    {
        if (actId == null)
            return null;
        Act act = (Act) em.createQuery("select a from Act a where a.actId = " + actId).getSingleResult();
        return act;
    }


    public Document findDocumentById(String docId) throws Hl7Exception
    {
        if (StrUtil.isEmpty(docId))
            return null;
        Document doc = (Document) em.createQuery("select doc from Document doc where doc.actId = " + docId).getSingleResult();
        return doc;
    }


    @SuppressWarnings("unchecked")
    public List<ActParticipation> findPrtcptnsByActId(Long ActId) throws Hl7Exception
    {
        List<ActParticipation> prtcptnsList = null;
        StringBuilder jpql = new StringBuilder("select actp from ActParticipation actp where actp.participationAct.actId =" + ActId + "");
        prtcptnsList = em.createQuery(jpql.toString()).getResultList();
        return prtcptnsList;
    }


    @Override
    public <T> List<T> getObjects(Class<T> clazz, Map<String, Object> conditions) throws Hl7Exception
    {

        StringBuilder jpql = new StringBuilder();
        jpql.append("select t from ");
        jpql.append(clazz.getSimpleName());
        jpql.append(" t where ");
        for (String key : conditions.keySet())
        {
            jpql.append("t.");
            jpql.append(key);
            jpql.append("=");
            Object value = conditions.get(key);
            if (value.getClass().equals(String.class))
            {
                jpql.append("'");
                jpql.append(value);
                jpql.append("'");
            }
            else
            {
                jpql.append(value);
            }
            jpql.append(" and");
        }
        jpql.append(" 1=1 ");

        @SuppressWarnings("unchecked")
        List<T> ts = em.createQuery(jpql.toString()).getResultList();
        return ts;
    }


    @Override
    public boolean validateEntityIIExsit(String id, String codingschemeEnName, String conceptCode)
    {
        StringBuilder jpql = new StringBuilder();
        jpql.append("select count(eii.entityIiId) from RimCoreEntyIi eii left join eii.rimCoreEntyCdSets cd where eii.extensionTxt='");
        jpql.append(id);
        jpql.append("' and cd.conceptCode='");
        jpql.append(conceptCode);
        jpql.append("' and cd.codingschemeEnName='");
        jpql.append(codingschemeEnName);
        jpql.append("'");
        Long count = (Long) em.createQuery(jpql.toString()).getSingleResult();
        if (count > 0)
        {
            log.info("AdmitManager-validateEntityIIExsit-号码已存在！:" + id);
            return true;
        }
        else
        {
            log.info("AdmitManager-validateEntityIIExsit-号码不存在！:" + id);
            return false;
        }
    }


    @Override
    public boolean validateRoleIIExsit(String id, String codingschemeEnName, String conceptCode)
    {
        StringBuilder jpql = new StringBuilder();
        jpql.append("select count(rii.roleIiId) from RimCoreRoleIi rii left join rii.rimCoreRoleCdSets cd where rii.extensionTxt='");
        jpql.append(id);
        jpql.append("' and cd.conceptCode='");
        jpql.append(conceptCode);
        jpql.append("' and cd.codingschemeEnName='");
        jpql.append(codingschemeEnName);
        jpql.append("'");
        Long count = (Long) em.createQuery(jpql.toString()).getSingleResult();
        if (count > 0)
        {
            log.info("AdmitManager-validateRoleIIExsit-号码已存在！:" + id);
            return true;
        }
        else
        {
            log.info("AdmitManager-validateRoleIIExsit-号码不存在！:" + id);
            return false;
        }
    }


    @Override
    public boolean validateRoleIIExsit(String id, RoleIICode identifierName)
    {
        StringBuilder jpql = new StringBuilder();
        jpql.append("select count(rii.roleIiId) from RimCoreRoleIi rii where rii.extensionTxt=");
        jpql.append(convertInJpql(id));

        jpql.append(" and rii.identifierName=");
        jpql.append(convertInJpql(identifierName.toString()));

        Long count = (Long) em.createQuery(jpql.toString()).getSingleResult();
        if (count > 0)
        {
            log.info("AdmitManager-validateRoleIIExsit-号码已存在！:" + id);
            return true;
        }
        else
        {
            log.info("AdmitManager-validateRoleIIExsit-号码不存在！:" + id);
            return false;
        }
    }
    
    public boolean actIIExist(String actii, String identifierName)
    {
        if (StrUtil.isEmpty(actii))
        {
            return false;
        }
        StringBuilder jpql = new StringBuilder();
        jpql.append("select aii.actIiId from RimCoreActIi aii where aii.extensionTxt='");
        jpql.append(actii);
        jpql.append("' and aii.identifierName='");
        jpql.append(identifierName == null ? "" : identifierName);
        jpql.append("'");
        @SuppressWarnings("unchecked")
        List<Long> iis = em.createQuery(jpql.toString()).getResultList();
        if (iis.isEmpty())
        {
            return false;
        }
        else
        {
            return true;
        }
    }


    @SuppressWarnings("unchecked")
    public boolean validateActIIExsit(String actii, String identifierName, String actId) throws Hl7Exception
    {
        if (StrUtil.isEmpty(actii))
        {
            return false;
        }
        StringBuilder jpql = new StringBuilder();
        jpql.append("select aii.rimCoreActs.actId from RimCoreActIi aii where aii.extensionTxt='");
        jpql.append(actii);
        jpql.append("' and aii.identifierName='");
        jpql.append(identifierName == null ? "" : identifierName);
        jpql.append("'");
        List<Long> iis = em.createQuery(jpql.toString()).getResultList();
        if (iis.isEmpty())
        {
            return false;
        }
        else
        {
            if (actId.equals(String.valueOf(iis.get(0))))
            {
                return false;
            }
            else
                return true;
        }
    }
    
    @SuppressWarnings("unchecked")
    public boolean validateEntyIIExsit(String entyii, String identifierName, String entityId) throws Hl7Exception
    {
        if (StrUtil.isEmpty(entyii))
        {
            return false;
        }
        StringBuilder jpql = new StringBuilder();
        jpql.append("select eii.rimCoreEntities.entityId from RimCoreEntyIi eii where eii.extensionTxt='");
        jpql.append(entyii);
        jpql.append("' and eii.identifierName='");
        jpql.append(identifierName == null ? "" : identifierName);
        jpql.append("'");
        List<Long> iis = em.createQuery(jpql.toString()).getResultList();
        if (iis.isEmpty())
        {
            return false;
        }
        else
        {
            if (entityId.equals(String.valueOf(iis.get(0))))
            {
                return false;
            }
            else
                return true;
        }
    }


    public Object convertInJpql(Object obj)
    {
        if (obj instanceof String)
        {
            return "'" + obj + "'";
        }
        else if (obj instanceof List)
        {
            return convertList((List<?>) obj);
        }
        else
        {
            return obj;
        }
    }


    public String convertList(List<?> list)
    {
        StringBuilder sb = new StringBuilder();
        if (!list.isEmpty())
        {
            sb.append("(");
            if (list.get(0) instanceof String)
            {

                for (int i = 0; i < list.size(); i++)
                {
                    if (i == 0)
                    {
                        sb.append("'");
                        sb.append(list.get(i));
                        sb.append("'");
                    }
                    else
                    {
                        sb.append(",");
                        sb.append("'");
                        sb.append(list.get(i));
                        sb.append("'");
                    }
                }
            }
            else
            {
                for (int i = 0; i < list.size(); i++)
                {
                    if (i == 0)
                    {

                        sb.append(list.get(i));

                    }
                    else
                    {
                        sb.append(",");

                        sb.append(list.get(i));

                    }
                }
            }
            sb.append(")");
        }
        return sb.toString();
    }


    @SuppressWarnings("unchecked")
    public List<? extends Act> queryResults(Map<String, Map<String, Object>> conditions, Class<?> targetClass, int pageNo, int pageSize)
        throws Hl7Exception
    {
        Query query = em.createQuery(constructJbql(conditions, targetClass, null));
        if (pageNo > 0 && pageSize > 0)
        {
            query.setFirstResult((pageNo - 1) * pageSize).setMaxResults(pageSize);
        }
        List<? extends Act> inves = query.getResultList();
        return inves;

    }


    public long queryCountResults(Map<String, Map<String, Object>> conditions, Class<?> targetClass) throws Hl7Exception
    {
        Query query = em.createQuery(constructJbql(conditions, targetClass, Long.class));
        Long count = (Long) query.getSingleResult();
        return count;
    }


    public String constructJbql(Map<String, Map<String, Object>> conditions, Class<?> targetActClass, Class<?> clazz, String targetObject)
    {
        StringBuilder target = new StringBuilder();
        StringBuilder condition = new StringBuilder();
        if (Long.class.equals(clazz))
        {
            if (StrUtil.isEmpty(targetObject))
            {
                targetObject = "act.actId";
            }

            target.append("select count(distinct ");
            target.append(targetObject);
            target.append(") from ");
        }
        else
        {

            if (StrUtil.isEmpty(targetObject))
            {
                targetObject = "act";
            }
            target.append("select distinct ");
            target.append(targetObject);
            target.append(" from ");
        }

        target.append(targetActClass.getSimpleName());
        target.append(" act ");

        condition.append(" where 1=1 ");
        // 主体对象条件
        if (conditions.get("act") != null)
        {
            if (conditions.get("act").get("classCode") != null)
            {
                condition.append(" and act.classCode=");
                condition.append(convertInJpql(conditions.get("act").get("classCode")));
            }
            if (conditions.get("act").get("codeEtsId") != null)
            {
                condition.append(" and act.codeEtsId=");
                condition.append(convertInJpql(conditions.get("act").get("codeEtsId")));
            }

            if (conditions.get("act").get("moodCode") != null)
            {
                condition.append(" and act.mood_Code=");
                condition.append(convertInJpql(conditions.get("act").get("moodCode")));
            }

            if (conditions.get("act").get("statusCode") != null)
            {
                condition.append(" and act.statusCode=");
                condition.append(convertInJpql(conditions.get("act").get("statusCode")));
            }
            
            if (conditions.get("act").get("actId") != null)
            {
                condition.append(" and act.actId=");
                condition.append(convertInJpql(conditions.get("act").get("actId")));
            }
            if (conditions.get("act").get("activityStartDateTs>") != null)
            {
                condition.append(" and act.activityStartDateTs>:from");

            }
            if (conditions.get("act").get("activityStartDateTs<") != null)
            {
                condition.append(" and act.activityStartDateTs<:to");

            }
            if (conditions.get("act").get("activityStartDateTs>=") != null)
            {
                condition.append(" and act.activityStartDateTs>=:from");

            }
            if (conditions.get("act").get("activityStartDateTs<=") != null)
            {
                condition.append(" and act.activityStartDateTs<=:to");

            }
            if (conditions.get("act").get("negationFlag") != null)
            {
                condition.append(" and act.negationFlag=");
                condition.append(convertInJpql(conditions.get("act").get("negationFlag")));
            }
            if (conditions.get("act").get("levelCodeEtsId") != null)
            {
                condition.append(" and act.levelCodeEtsId in ");
                condition.append(convertInJpql(conditions.get("act").get("levelCodeEtsId")));
            }
        }
        
        //关联RimCoreActCdSets
        if( conditions.get("acd") != null )
        {
            target.append(" left join act.actCdSetsList acd ");
            if(conditions.get("acd").get("attributeTypeCode") != null)
            {
                condition.append(" and acd.attributeTypeCode=");
                condition.append(convertInJpql(conditions.get("acd").get("attributeTypeCode")));
            }
            if(conditions.get("acd").get("conceptCode") != null)
            {
                condition.append(" and acd.conceptCode=");
                condition.append(convertInJpql(conditions.get("acd").get("conceptCode")));
            }
        }

        // 关联Actii对象
        if (conditions.get("act") != null&&conditions.get("aii") != null)
        {
            target.append(" left join act.actsIiList aii ");
            if (conditions.get("aii").get("identifierName") != null)
            {
                condition.append(" and aii.identifierName=");
                condition.append(convertInJpql(conditions.get("aii").get("identifierName")));
            }
            if (conditions.get("aii").get("extensionTxt") != null)
            {
                condition.append(" and aii.extensionTxt =");
                condition.append(convertInJpql(conditions.get("aii").get("extensionTxt")));
            }
            if (conditions.get("aii").get("clinicNo") != null)
            {
                condition.append(" and aii.clinicNo =");
                condition.append(convertInJpql(conditions.get("aii").get("clinicNo")));
            }
        }
        
        // 关联prtcptns对象
        if (conditions.get("part") != null)
        {
            target.append(" left join act.prtcptnsActList part ");
            if (conditions.get("part").get("typeCode") != null)
            {
                condition.append(" and part.typeCode=");
                condition.append(convertInJpql(conditions.get("part").get("typeCode")));
            }
            if (conditions.get("part").get("signatureCodeEtsId") != null)
            {
                condition.append(" and part.signatureCodeEtsId=");
                condition.append(convertInJpql(conditions.get("part").get("signatureCodeEtsId")));
            }
            if (conditions.get("part").get("statusCodeOrNull") != null)
            {
                condition.append(" and (part.statusCode=");
                condition.append(convertInJpql(conditions.get("part").get("statusCodeOrNull")));
                condition.append(" or part.statusCode is null) ");
            }
            if (conditions.get("part").get("statusCode") != null)
            {
                condition.append(" and part.statusCode=");
                condition.append(convertInJpql(conditions.get("part").get("statusCode")));
            }
            if (conditions.get("part").get("statusCodeIn") != null)
            {
                condition.append(" and part.statusCode in ");
                condition.append(convertInJpql(conditions.get("part").get("statusCodeIn")));
            }

        }

        // 关联role对象
        if (conditions.get("part") != null && conditions.get("r") != null)
        {
            target.append(" left join part.roleParticipation r ");

            if (conditions.get("r").get("roleId") != null)
            {
                condition.append(" and r.roleId=");
                condition.append(convertInJpql(conditions.get("r").get("roleId")));
            }

            if (conditions.get("r").get("classCode") != null)
            {
                condition.append(" and r.classCode =");
                condition.append(convertInJpql(conditions.get("r").get("classCode")));
            }

            if (conditions.get("r").get("codeEtsId") != null)
            {
                condition.append(" and r.codeEtsId =");
                condition.append(convertInJpql(conditions.get("r").get("codeEtsId")));
            }

        }
        

        // 关联roleii对象
        if (conditions.get("r") != null && conditions.get("rii") != null)
        {
            target.append(" left join r.roleIiList rii ");

            if (conditions.get("rii").get("identifierName") != null)
            {
                condition.append(" and rii.identifierName =");
                condition.append(convertInJpql(conditions.get("rii").get("identifierName")));
            }
            if (conditions.get("rii").get("extensionTxt") != null)
            {
                condition.append(" and rii.extensionTxt =");
                condition.append(convertInJpql(conditions.get("rii").get("extensionTxt")));
            }

        }

        // 关联RoleLink对象
        if (conditions.get("r") != null && conditions.get("link") != null && conditions.get("tar") != null)
        {
            target.append(" left join r.sourceRoleRimCoreRoleLink link left join link.targetRole tar ");
            if (conditions.get("link").get("typeCode") != null)
            {
                condition.append(" and link.typeCode=");
                condition.append(convertInJpql(conditions.get("link").get("typeCode")));
            }
            if (conditions.get("tar").get("roleId") != null)
            {
                condition.append(" and tar.roleId=");
                condition.append(convertInJpql(conditions.get("tar").get("roleId")));
            }
        }
        
        // 关联角色playEntity对象
        if (conditions.get("act") != null && conditions.get("part") != null && conditions.get("r") != null && conditions.get("playEnty") != null)
        {
            target.append(" left join r.playerEntities playEnty");
            if(conditions.get("playEnty").get("classCode") != null)
            {
                condition.append(" and playEnty.classCode = ");
                condition.append(convertInJpql(conditions.get("playEnty").get("classCode")));
            }
            if(conditions.get("playEnty").get("codeEtsId") != null)
            {
                condition.append(" and playEnty.codeEtsId = ");
                condition.append(convertInJpql(conditions.get("playEnty").get("codeEtsId")));
            }
        }
        
        // 关联角色playEntity对象的entyNamesList
        if (conditions.get("act") != null && conditions.get("part") != null && conditions.get("r") != null && conditions.get("playEnty") != null
                && conditions.get("en") !=null )
        {
            target.append(" left join playEnty.entyNamesList en ");
        }
        
        // 关联角色playEntity对象的entyNamesList的entyNameUsesList
        if (conditions.get("act") != null && conditions.get("part") != null && conditions.get("r") != null && conditions.get("playEnty") != null
                && conditions.get("en") !=null && conditions.get("enu") !=null )
        {
            target.append(" left join en.entyNameUsesList enu ");
            if (conditions.get("enu").get("use") != null)
            {
                condition.append(" and enu.use=");
                condition.append(convertInJpql(conditions.get("enu").get("use")));
            }
        }
        

        // 关联角色scopeEntity对象
        if (conditions.get("act") != null && conditions.get("part") != null && conditions.get("r") != null && conditions.get("scopeEnty") != null)
        {
            target.append(" left join r.scoperEntities scopeEnty");
        }

        // 关联 角色scopeEntity所扮演的角色
        if (conditions.get("act") != null && conditions.get("part") != null && conditions.get("r") != null && conditions.get("scopeEnty") != null
                && conditions.get("playRole") != null)
        {
            target.append(" left join scopeEnty.playerRolesList playRole");
            if (conditions.get("playRole").get("roleId") != null)
            {
                condition.append(" and playRole.roleId =");
                condition.append(convertInJpql(conditions.get("playRole").get("roleId")));
            }
        }
        
        //
        if (conditions.get("act") != null && conditions.get("part") != null && conditions.get("r") != null && conditions.get("scopeEnty") != null
                && conditions.get("playRole") != null && conditions.get("playEnty2") != null )
        {
            target.append(" left join playRole.playerEntities playEnty2 ");
        }
        
        if (conditions.get("act") != null && conditions.get("part") != null && conditions.get("r") != null && conditions.get("scopeEnty") != null
                && conditions.get("playRole") != null && conditions.get("playEnty2") != null && conditions.get("en2") != null )
        {
            target.append(" left join playEnty2.entyNamesList en2 ");
            if (conditions.get("en2").get("formatted") != null)
            {
                condition.append(" and en2.formatted=");
                condition.append(convertInJpql(conditions.get("en2").get("formatted")));
            }
        }
        
        if (conditions.get("act") != null && conditions.get("part") != null && conditions.get("r") != null && conditions.get("scopeEnty") != null
                && conditions.get("playRole") != null && conditions.get("playEnty2") != null && conditions.get("en2") != null 
                    && conditions.get("enu2") != null )
        {
            target.append(" left join en2.entyNameUsesList enu2 ");
            if (conditions.get("enu2").get("use") != null)
            {
                condition.append(" and enu2.use=");
                condition.append(convertInJpql(conditions.get("enu2").get("use")));
            }
        }
        
        // 排序
        if (conditions.get("order by") != null)
        {
            condition.append(" order by ");
            if (conditions.get("order by").get("desc") != null)
            {
                condition.append(conditions.get("order by").get("desc"));
                condition.append(" desc  ");
            }
            else if (conditions.get("order by").get("asc") != null)
            {
                condition.append(conditions.get("order by").get("asc"));
                condition.append(" asc ");
            }
        }

        String jbql = target.toString() + condition.toString();

        log.info("组装好的jpql语句为:" + jbql);
        return jbql;
    }


    public String constructJbql(Map<String, Map<String, Object>> conditions, Class<?> targetClass, Class<?> clazz) throws Hl7Exception
    {

        return constructJbql(conditions, targetClass, clazz, null);
    }

}
